import os
import sys
import time
import threading
import platform
import subprocess
import argparse


def kill_yumdownloader(rpm_path, thr):
    cmd = "ls %s | grep '\.rpm'" % rpm_path
    res = os.popen(cmd).read()
    while not res:
        if not thr.is_alive():
            break
        time.sleep(5)
        res = os.popen(cmd).read()
    cmd = "ps -ef | grep yumdownloader | awk '{print $2}' | xargs kill -9"
    os.system(cmd)


def set_rpm_list(rpm_list_file, arch, rpm_path, config=None, repo=None):
    if config and repo:
        para = "-c %s --repo %s" % (config, repo)
    elif config:
        para = "-c %s" % config
    else:
        para = "" 
    cmd = "yum list --installroot=%s --available %s | grep -E '\.%s|\.noarch' | grep -v 'debugsource' | grep -v 'debuginfo'| awk '{print $1}' > %s" % (rpm_path, para, arch, rpm_list_file)
    print(cmd)
    if os.system(cmd) == 0:
        pass
    else:
        return 1
    return 0


def set_exclude(f, err):
    exclude = ""
    rpm_list = []
    for line in err.splitlines():
        if "requires" in line:
            f.write("%s\n" % line)
            print(line)
            if "package" in line:
                pkg = line.split("package")[1].split("requires")[0].strip()
                if pkg not in rpm_list:
                    rpm_list.append(pkg)
        if "needed by" in line:
            f.write("%s\n" % line)
            print(line)
            pkg = line.split("needed by")[1].strip()
            if pkg not in rpm_list:
                rpm_list.append(pkg)
    for p in rpm_list:
        exclude = exclude + " -x %s" % p
    print("+++++++ %s ++++++++" % exclude)
    return exclude


def set_delete_list(err, delete_list, rpm_list_file):
     for line in err.splitlines():
         if "No package" in line:
             pkg = line.split("No package")[1].split("available")[0].strip()
             cmd = "sed -i '/{0}/d' {1}".format(pkg, rpm_list_file)
             if os.system(cmd) == 0:
                 pass
             if pkg not in delete_list:
                 delete_list.append(pkg)


def check_dep(rpm_list_file, check_log_file, delete_rpm_list_file, rpm_path, config=None, repo=None):
    if config and repo:
        para = "-c %s --repo %s" % (config, repo)
    elif config:
        para = "-c %s" % config
    else:
        para = "" 
    cmd = "rm -rf %s && rm -rf %s && rm -rf %s && rm -rf %s/*.rpm" % (rpm_list_file, check_log_file, delete_rpm_list_file, rpm_path)
    if os.system(cmd) == 0:
        pass
    arch = platform.machine()
    if set_rpm_list(rpm_list_file, arch, rpm_path, config=config, repo=repo):
        sys.exit(1)
    delete_list = []
    cmd="yumdownloader --resolve --installroot={0} --destdir={1} $(cat {2} | tr '\n' ' ') {3}".format(rpm_path, rpm_path, rpm_list_file, para)
    print(cmd)
    p=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8")
    out, err = p.communicate()
    with open(check_log_file, 'w') as f:
        while err:
            if "Problem" not in err and "No package" not in err:
                break
            exclude = set_exclude(f, err)
            print("================= %s ===" % exclude)

            cmd="yumdownloader --resolve --installroot=/tmp --destdir=/tmp $(cat {0} | tr '\n' ' ') {1} {2}".format(rpm_list_file, exclude, para)
            p=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8")
            out, err = p.communicate()
            if err:
                set_delete_list(err, delete_list, rpm_list_file)

            cmd="yumdownloader --resolve --installroot=/tmp --destdir=/tmp $(cat {0} | tr '\n' ' ') {1}".format(rpm_list_file, para)
            p=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8")
            out, err = p.communicate()
    for p in delete_list:
        cmd = "echo {0} >> {1}".format(p, delete_rpm_list_file)
        if os.system(cmd) == 0:
            pass
    cmd = "sed -i 's/\.%s//g' {0} && sed -i 's/\.noarch//g' {1}".format(delete_rpm_list_file, delete_rpm_list_file)
    if os.system(cmd) == 0:
        pass
    print("=================== exclude rpm list start ======================")
    print(os.popen("cat %s && rm -rf %s/*.rpm" % (delete_rpm_list_file, rpm_path)).read())
    print("=================== exclude rpm list end ======================")


par = argparse.ArgumentParser()
par.add_argument("-d", "--dest_rpm_path", help="path for rpm", required=True)
par.add_argument("-l", "--rpm_list_file", help="file for rpm list", required=True)
par.add_argument("-f", "--check_log_file", help="file for checking log", required=True)
par.add_argument("-e", "--exclude_rpm_list_file", help="file for rpms which are exclude", required=True)
par.add_argument("-c", "--config", help="config file repofile", default=None, required=False)
par.add_argument("-r", "--repo", help="name of repo", default=None, required=False)
args = par.parse_args()
print(args.config)

t1 = threading.Thread(target=check_dep, args=(args.rpm_list_file, args.check_log_file, args.exclude_rpm_list_file, args.dest_rpm_path, args.config, args.repo))
t1.start()
t2 = threading.Thread(target=kill_yumdownloader, args=(args.dest_rpm_path, t1))
t2.start()
